package com.witsight.cassandra.util;

import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.witsight.platform.util.lang.StringUtil;

/**
 * 说明：Cql解析器
 * 
 * @Title: CqlBuilder.java
 * @Package com.witsight.cassandra.util
 * @See: {@link CqlTextTemplates}
 * Copyright: Copyright (c) 2017 
 * Company:sany huax witsight team by product
 * @author: penght
 * @date: 2017年9月21日 下午5:52:00
 * @version: V1.0
 *
 */
public class CqlBuilder {
	private static final Logger log = LoggerFactory.getLogger(CqlBuilder.class);
	// 替换的表的标识
	private static final String TABLE_TAG = "{table}";
	// where 字符串
	private static final String CQL_WHERE = "WHERE";
	private static final String CQL_WHERE_AND_REGEX = "(?i)" + CQL_WHERE + "\\s+and";
	private static final String CQL_WHERE_REGEX = "(?i)" + CQL_WHERE;
	private static final String ALLOW_FILTERING_REGEX = "(?i)ALLOW\\s+FILTERING";
	private static final String ORDER_BY_PART = "(?iu)\\s+order\\s+by\\s+.*$";
	private static final String IDENTIFIER = "[\\p{Lu}\\P{InBASIC_LATIN}\\p{Alnum}._$]+";
	private static final Pattern NAMED_PARAMETER = Pattern.compile(":" + IDENTIFIER + "|\\#" + IDENTIFIER,
			CASE_INSENSITIVE);
	private static final String SIMPLE_COUNT_VALUE = "$2";
	private static final String COMPLEX_COUNT_VALUE = "$3$6";
	private static final String IDENTIFIER_GROUP = String.format("(%s)", IDENTIFIER);
	private static final String COUNT_REPLACEMENT_TEMPLATE = "select count(%s) $5$6";
	private static final int VARIABLE_NAME_GROUP_INDEX = 4;
	private static final Pattern COUNT_MATCH;
	static {

		StringBuilder builder = new StringBuilder();
		builder = new StringBuilder();
		builder.append("(select\\s+((distinct )?(.+?)?)\\s+)?(from\\s+");
		builder.append(IDENTIFIER).append(")");
//		builder.append("(?:\\s+as)?\\s+)");
//		builder.append(IDENTIFIER_GROUP);
		builder.append("(.*)");
		System.out.println(builder.toString());
		COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);

	}
	/**
	 * 
	 * 说明：cassandra cql解析
	 * 
	 * @Title: cassandraParse
	 * @See: {@link #cassandraParse(String, Map)}
	 * @author penght
	 * @param sql
	 *            sql原形
	 * @param params
	 *            参数
	 * @return String 处理后的sql
	 * @date: 2016年11月15日 下午1:56:59
	 */
	public static String parse(String sql, Map<String, ?> params) {
		if (log.isDebugEnabled()) {
			log.debug("cassandra org cql : {}", sql);
		}
		if (params == null)
			return sql;

		String statement = CqlTextTemplates.replaceTemplate(sql, params);
		statement = CqlTextTemplates.removeOptionalFrag(statement, params);
		statement = cqlHandled(statement);
		if (log.isDebugEnabled()) {
			log.debug("run cql : {}" + statement);
		}
		return statement; // To change body of created methods use File | Settings | File Templates.
	}
	
	/**
	 * 说明：替换{table}的表名称
	 * @Title: getQueryString
	 * @See: {@link #getQueryString(String, String)}
	 * @author penght
	 * @param query sql
	 * @param tableName 表名称
	 * @return sql
	 * @date: 2017年9月22日 上午10:15:24
	 */
	public static String getQueryString (String query, String tableName) {
		if (StringUtil.contains(query, TABLE_TAG) && StringUtil.isNotEmpty(tableName)) {
			return StringUtil.replace(query, TABLE_TAG, tableName);
		}
		if (log.isWarnEnabled()) {
			log.warn("{}'s TABLE_TAG is config ,but tableName haven't config.", TABLE_TAG);
		}
		return query;
	}
	/**
	 * 
	 * 说明：处理正规的cql语言
	 * @Title: cqlHandled
	 * @See: {@link #cqlHandled(String)}
	 * @author penght
	 * @param query 
	 * @return 正规的cql语言
	 * @date: 2017年9月22日 上午11:41:23
	 */
	private static String cqlHandled(String query) {
		String cql = query;;
		if (!hasNamedParameter(query) && StringUtil.containsIgnoreCase(cql, CQL_WHERE)) {
			// 如果条件为空，需要将where删除
			cql = StringUtil.removePattern(StringUtil.removePattern(cql, CQL_WHERE_REGEX), ALLOW_FILTERING_REGEX);
		} else if (StringUtil.containsIgnoreCase(cql, CQL_WHERE)) {
			// 如果条件不为空，删除第一个and
			cql = StringUtil.replacePattern(cql, CQL_WHERE_AND_REGEX, CQL_WHERE);
		}
		
		return cql;
	}
	
	/**
	 * Returns whether the given query contains named parameters.
	 * 
	 * @param query can be {@literal null} or empty.
	 * @return
	 */
	public static boolean hasNamedParameter(String query) {
		return StringUtils.hasText(query) && NAMED_PARAMETER.matcher(query).find();
	}
	/**
	 * Creates a count projected query from the given original query.
	 * 
	 * @param originalQuery must not be {@literal null}.
	 * @param countProjection may be {@literal null}.
	 * @return
	 * @since 1.6
	 */
	public static String createCountQueryFor(String originalQuery) {
		return createCountQueryFor(originalQuery , "1");
	}
	/**
	 * Creates a count projected query from the given original query.
	 * 
	 * @param originalQuery must not be {@literal null}.
	 * @param countProjection may be {@literal null}.
	 * @return
	 * @since 1.6
	 */
	public static String createCountQueryFor(String originalQuery, String countProjection) {

		Assert.hasText(originalQuery, "OriginalQuery must not be null or empty!");

		Matcher matcher = COUNT_MATCH.matcher(originalQuery);
		String countQuery = null;

		if (countProjection == null) {

			String variable = matcher.matches() ? matcher.group(VARIABLE_NAME_GROUP_INDEX) : null;
			boolean useVariable = variable != null && StringUtils.hasText(variable) && !variable.startsWith("new")
					&& !variable.startsWith("count(") && !variable.contains(",");

			String replacement = useVariable ? SIMPLE_COUNT_VALUE : COMPLEX_COUNT_VALUE;
			countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, replacement));
		} else {
			countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, countProjection));
		}

		return countQuery.replaceFirst(ORDER_BY_PART, "");
	}
	
//	public static void main(String[] args) {
//		String c = createCountQueryFor("select * from simplet");
//		System.out.println(c);
//	}
}
